package kube

import (
	"errors"
	"fmt"
	"gitee.com/lllgo/opsctl/pkg/cmd"
	"gitee.com/lllgo/opsctl/pkg/conf"
	"gitee.com/lllgo/opsctl/pkg/tools"
	"github.com/spf13/cobra"
	"path/filepath"
	"strings"
)

// TODO 暂时未想到同步配置修改属性到配置文件的方式

func init() {
	registerSubCmd(addMasterCmd(), delMasterCmd(), addNodeCmd(), delNodeCmd(), addEtcdCmd(), delEtcdCmd())
}

func newOperation(opr, nodeType string, f func(name string, host tools.Host) error) *cobra.Command {
	oprDesc := "添加"
	cmdType := conf.Add
	if opr == "del" {
		oprDesc = "删除"
		cmdType = conf.Remove
	}

	desc := oprDesc + nodeType + "节点，支持" + oprDesc + "多个节点"

	var cmd = &cobra.Command{
		Use:   opr + "-" + nodeType,
		Short: desc,
		Long:  desc,
		Args: func(cmd *cobra.Command, args []string) error {
			if len(args) == 0 {
				return fmt.Errorf("请设置要添加的NodeIP")
			}
			return nil
		},
		Example: oprDesc + `一个节点
opsctl kube ` + opr + "-" + nodeType + ` k8s-1
` + oprDesc + `两个个节点
opsctl kube ` + opr + "-" + nodeType + ` k8s-1 k8s-2`,
		RunE: func(command *cobra.Command, args []string) error {
			hosts := cmd.GetHostsWithTag(cmdType, CmdName+"-"+nodeType, args...)
			if len(hosts) == 0 {
				return errors.New("错误的服务器:" + strings.Join(args, ","))
			}
			for _, host := range hosts {

				if f != nil {
					if err := f(host.Name, host); err != nil {
						return err
					}
				}

				conf.WriteComponentConfig(kubeConfig, CmdName)

				return nil

			}
			return nil
		},
	}

	return cmd
}

func addMasterCmd() *cobra.Command {
	cmd := newOperation("add", "master", func(hostName string, host tools.Host) error {
		for _, v := range kubeConfig.Master {
			if v == hostName {
				return fmt.Errorf("master %s 已经存在", hostName)
			}
		}

		kubeConfig.Master = append(kubeConfig.Master, hostName)
		genTmpl()

		playbook := tools.NewPlaybook(kubeConfig.Dir, "", filepath.Join("tools", "03.addmaster.yml"))
		playbook.Params = map[string]string{
			"NODE_TO_ADD": host.IP(),
		}
		if err := playbook.Run(); err != nil {
			return err
		}

		playbook = tools.NewPlaybook(kubeConfig.Dir, "", "05.kube-node.yml")
		playbook.Params = map[string]string{
			"MASTER_CHG": "yes",
		}
		playbook.Tags = []string{"restart_lb"}

		if err := playbook.Run(); err != nil {
			return err
		}

		return nil
	})

	return cmd
}

func delMasterCmd() *cobra.Command {
	cmd := newOperation("del", "master", func(hostName string, host tools.Host) error {
		for i, v := range kubeConfig.Master {
			if v == hostName {
				playbook := tools.NewPlaybook(kubeConfig.Dir, "", filepath.Join("tools", "13.delmaster.yml"))
				playbook.Params = map[string]string{"NODE_TO_DEL": host.IP()}
				if err := playbook.Run(); err != nil {
					return err
				}

				playbook = tools.NewPlaybook(kubeConfig.Dir, "", "05.kube-node.yml")
				playbook.Params = map[string]string{"MASTER_CHG": "yes"}
				playbook.Tags = []string{"restart_lb"}
				if err := playbook.Run(); err != nil {
					return err
				}

				kubeConfig.Master = append(kubeConfig.Master[0:i], kubeConfig.Master[i+1:]...)

				return nil
			}
		}
		return fmt.Errorf("master %s 不存在", hostName)
	})

	return cmd
}

func addNodeCmd() *cobra.Command {
	cmd := newOperation("add", "node", func(hostName string, host tools.Host) error {
		for _, v := range kubeConfig.Node {
			if v == hostName {
				return fmt.Errorf("node %s 已经存在", hostName)
			}
		}

		kubeConfig.Node = append(kubeConfig.Node, hostName)
		genTmpl()

		playbook := tools.NewPlaybook(kubeConfig.Dir, "", filepath.Join("tools", "02.addnode.yml"))

		playbook.Params = map[string]string{"NODE_TO_ADD": host.IP()}

		return playbook.Run()
	})

	return cmd
}

func delNodeCmd() *cobra.Command {
	cmd := newOperation("del", "node", func(hostName string, host tools.Host) error {
		for i, v := range kubeConfig.Node {
			if v == hostName {

				playbook := tools.NewPlaybook(kubeConfig.Dir, "", filepath.Join("tools", "12.delnode.yml"))
				playbook.Params = map[string]string{"NODE_TO_DEL": host.IP()}
				if err := playbook.Run(); err != nil {
					return err
				}

				kubeConfig.Node = append(kubeConfig.Node[0:i], kubeConfig.Node[i+1:]...)

				return nil
			}
		}
		return fmt.Errorf("node %s 不存在", hostName)
	})

	return cmd
}

// TODO Etcd节点管理未走通
func addEtcdCmd() *cobra.Command {
	cmd := newOperation("add", "etcd", func(hostName string, host tools.Host) error {
		for _, v := range kubeConfig.Etcd {
			if v == hostName {
				return fmt.Errorf("etcd %s 已经存在", hostName)
			}
		}

		kubeConfig.Etcd = append(kubeConfig.Etcd, hostName)
		addEtcdDesc(hostName, len(kubeConfig.Etcd))
		genTmpl()

		playbook := tools.NewPlaybook(kubeConfig.Dir, "", filepath.Join("tools", "01.addetcd.yml"))
		playbook.Params = map[string]string{"NODE_TO_ADD": host.IP()}
		if err := playbook.Run(); err != nil {
			return err
		}

		playbook = tools.NewPlaybook(kubeConfig.Dir, "", "04.kube-master.yml")
		playbook.Tags = []string{"restart_master"}

		return playbook.Run()
	})

	cmd.Hidden = true

	return cmd
}

// TODO Etcd节点管理未走通
func delEtcdCmd() *cobra.Command {
	cmd := newOperation("del", "etcd", func(hostName string, host tools.Host) error {
		for i, v := range kubeConfig.Etcd {
			if v == hostName {
				playbook := tools.NewPlaybook(kubeConfig.Dir, "", filepath.Join("tools", "11.deletcd.yml"))
				playbook.Params = map[string]string{"NODE_TO_DEL": host.IP()}
				playbook.Args = []string{"-vvvv"}
				if err := playbook.Run(); err != nil {
					return err
				}

				playbook = tools.NewPlaybook(kubeConfig.Dir, "", "04.kube-master.yml")
				playbook.Tags = []string{"restart_master"}
				if err := playbook.Run(); err != nil {
					return err
				}

				kubeConfig.Etcd = append(kubeConfig.Etcd[0:i], kubeConfig.Etcd[i+1:]...)

				return nil
			}
		}
		return fmt.Errorf("etcd %s 不存在", hostName)
	})

	cmd.Hidden = true
	return cmd
}
